package de.pharmacontrol.rfcserver.handler;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.logging.Logger;

import javax.ejb.EJB;
import javax.ejb.Singleton;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.xml.sax.SAXException;

import com.sap.conn.jco.AbapClassException;
import com.sap.conn.jco.AbapException;
import com.sap.conn.jco.JCoFunction;
import com.sap.conn.jco.JCoParameterField;
import com.sap.conn.jco.JCoParameterFieldIterator;
import com.sap.conn.jco.JCoStructure;
import com.sap.conn.jco.server.JCoServerContext;

import de.pharmacontrol.pilot.entities.DeviceCounter;
import de.pharmacontrol.pilot.entities.Order;
import de.pharmacontrol.pilot.entities.OrderData;
import de.pharmacontrol.psa.beans.interfaces.LoggerService;
import de.pharmacontrol.psa.beans.interfaces.OrderService;

@Singleton
public class GetOrderResultsFunctionHandler extends FunctionHandler {


	@EJB
	LoggerService logger;

	@EJB
	OrderService orderBean;
	
	/**
	 * <Z_PPFM_PCE_ORDER_RESULTS_GET> <INPUT> <I_HEADER>
	 * <ODERNR>000001001518</ODERNR> <ACTION>3</ACTION> </I_HEADER> </INPUT>
	 * <OUTPUT> <E_RESULTS> <AUFNR></AUFNR> <STATUS></STATUS>
	 * <RESSOURCE></RESSOURCE> <LAYOUT></LAYOUT> <MATNR></MATNR> <MAKTX></MAKTX>
	 * <CHARG></CHARG> <HSDAT></HSDAT> <VFDAT></VFDAT>
	 * <HSDAT_PRINT></HSDAT_PRINT> <VFDAT_PRINT></VFDAT_PRINT>
	 * <CHARGE_PRINT></CHARGE_PRINT> <DRUCK_INFO1></DRUCK_INFO1>
	 * <DRUCK_INFO2></DRUCK_INFO2> <DRUCK_INFO3></DRUCK_INFO3> <CIP></CIP>
	 * <GS1_BATCH></GS1_BATCH> <GS1_HSDAT></GS1_HSDAT> <GS1_VFDAT></GS1_VFDAT>
	 * <COUNTER_SUCCESS>0000000</COUNTER_SUCCESS>
	 * <COUNTER_ERROR>0000000</COUNTER_ERROR>
	 * <COUNTER_TOTAL>0000000</COUNTER_TOTAL> </E_RESULTS> </OUTPUT>
	 * </Z_PPFM_PCE_ORDER_RESULTS_GET>
	 */
	@Override
	public void handleRequest(JCoServerContext serverCtx, JCoFunction function) throws AbapException, AbapClassException {

		final String xml = function.toXML();
		if (xml == null || xml.isEmpty()) {
			return;
		}
		Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).info(this.getClass().getName() + " receives:" + xml);
		
		Order order = null;
		
		try {
			order = getParsedOrder(xml);
		} catch (Exception e) {
			e.printStackTrace();
			return;
		}
		if (order == null){
			return;
		}
		Order updatedOrder = orderBean.updateOrder(order);
		
		if (function.getExportParameterList() != null) {
			JCoParameterFieldIterator it = function.getExportParameterList().getParameterFieldIterator();
			while (it.hasNextField()) {
				JCoParameterField parameterField = it.nextParameterField();
				if (parameterField.isStructure()) {
					String name = parameterField.getName(); 
					if (!name.equals("E_RESULTS")){
						continue;
					}
					JCoStructure structure = parameterField.getStructure();

					updateStructure(structure, "ODERNR", updatedOrder.getName());
					updateStructure(structure, "STATUS", String.valueOf(updatedOrder.getStatus()));
					
					if (updatedOrder.getLineFormat() != null && updatedOrder.getLineFormat().getLine() != null){
						updateStructure(structure, "RESSOURCE", updatedOrder.getLineFormat().getLine().getName());
					}
					if (updatedOrder.getLineFormat() != null){
						updateStructure(structure, "LAYOUT", updatedOrder.getLineFormat().getName());
					}

					for (OrderData od : updatedOrder.getOrderData()){
						if (od.getValue() != null && !od.getValue().isEmpty()){
							OrderdataMapping map = null;
							try {
								map = OrderdataMapping.valueOf(od.getAi().getAi());
								if (map != null){
									updateStructure(structure, map.name(), od.getValue());
								}
							} catch (Exception e) {
								e.printStackTrace();
							}

						}
					}

					//TODO: add counters
					if (updatedOrder.getDeviceCounters() != null && updatedOrder.getDeviceCounters().size() > 0) {
						for (DeviceCounter dc : updatedOrder.getDeviceCounters()) {
							updateStructure(structure, "COUNTER_SUCCESS", convertLongToString(dc.getGoodCount(), 7));
							updateStructure(structure, "COUNTER_ERROR", convertLongToString(dc.getBadCount(), 7));
							updateStructure(structure, "COUNTER_TOTAL", convertLongToString(dc.getTotalCount(), 7));
							break;
						}
					}

					

				}

			}
		}
	}
	
	private String convertLongToString(long sn, int length) {

		String s = Long.toString(sn);
		if (s.length() >= length) {
			return s;
		}
		return "00000000000000000000".substring(s.length(), length).concat(s);
	}
	
	private boolean updateStructure(final JCoStructure structure, String key, String value){
		try {
			structure.setValue(key, value);
			return true;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}
	
	public Order getParsedOrder(String xml) throws XPathExpressionException, ParserConfigurationException, SAXException, IOException {
		DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();

		DocumentBuilder builder = domFactory.newDocumentBuilder();
		Document doc = builder.parse(new ByteArrayInputStream(xml.getBytes()));

		XPath xpath = XPathFactory.newInstance().newXPath();
		String orderName = getNodeValue(xpath, doc, "Z_PPFM_PCE_ORDER_RESULTS_GET/INPUT/I_HEADER/ODERNR/text()");

		Order order = orderBean.findOrderByName(orderName);

		return order;
	}
	
}
